package zf.media.audio
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.media.Sound;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.getDefinitionByName;

	/**
	 * 声音管理器，用于对所用声音的控制，单例 
	 * @author 张峰
	 * 
	 */
	public class SoundManage extends EventDispatcher
	{
		private var list:Array;
		private var data:Object;
		private static var instance:SoundManage;
		public function SoundManage()
		{
			if(instance)
			{
				throw new Error("This is Singleton");
				return;
			}
			list=new Array();
			data=new Object();
			instance=this;
		}
		/**
		 * 获得单例 
		 * @return SoundManage
		 * 
		 */
		public static function getInstance():SoundManage
		{
			if(instance)
			{
				return instance;
			}
			return new SoundManage();
		}
		public function get length():uint
		{
			return list.length;
		}
		/**
		 * 播放声音 
		 * @param id 声音ID
		 * @param startTime 开始时间（毫秒）
		 * @param soundTransform 声道
		 * 
		 */
		public function play(id:String,startTime:Number=0,soundTransform:SoundTransform=null):void
		{
			var su:SoundUnit=data[id];
			if(su)
			{
				su.play(startTime,soundTransform);
			}
		}
		
		/**
		 * 继续播放声音，如果声音在播放，则继续播放；如果停止，则从上次断点继续播放
		 * @param id 声音ID
		 * 
		 */
		public function playContinue(id:String):void
		{
			var su:SoundUnit=data[id];
			if(su)
			{
				if(!su.isPlay)
				{
					su.playPause();
				}
			}
		}

		/**
		 * 播放 暂停
		 * @param id 声音ID
		 * 
		 */
		public function playPause(id:String):void
		{
			var su:SoundUnit=data[id];
			if(su)
			{
				su.playPause();
			}
		}
		/**
		 * 暂停声音 
		 * @param id 声音ID
		 * 
		 */
		public function pause(id:String):void
		{
			var su:SoundUnit=data[id];
			if(su)
			{
				su.pause();
			}
		}
		/**
		 * 暂停所有声音 
		 * 
		 */
		public function pauseAll():void
		{
			var su:SoundUnit;
			for(var i:uint=0;i<list.length;i++)
			{
				su=data[list[i]];
				if(su)
				{
					su.pause();
				}
			}
		}
		/**
		 * 设置声音的音量和平移 
		 * @param id 声音ID
		 * @param volume 音量
		 * @param pan 声音平移
		 * 
		 */
		public function setSoundVolumeAndPan(id:String,volume:Number,pan:Number=0):void
		{
			var su:SoundUnit=data[id];
			su.volume=volume;
			su.pan=pan;
		}
		/**
		 * 控制可显示对象的音量和平移，如果要控制全局音量，请传递根显示对象，不能为stage，一般为 this 关键字 
		 * @param sp 可显示对象
		 * @param volume 音量
		 * @param pan 声音平移
		 */
		public function setSpriteVolumeAndPan(sp:Sprite,volume:Number,pan:Number=0):void
		{
			var st:SoundTransform = new SoundTransform(volume,pan);
			sp.soundTransform = st;
		}
		/**
		 * 添加一个声音,如果ID重复将覆盖先前的声音
		 * @param id 声音ID
		 * @param sound 声音
		 * @param autoPlay 是否自动播放
		 * @param loop 循环播放次数，0，1均为播放1次，SoundUnit.INFINITI (-1000) 为无限循环
		 * @param autoRemove 是否自动删除，如果是将在循环播放彻底结束时候删除
		 * 
		 */
		public function addSound(id:String,sound:Sound,autoPlay:Boolean=true,loop:int=0,autoRemove:Boolean=true):void
		{
			var su:SoundUnit=new SoundUnit(id,sound);
			var index:int=list.indexOf(id);
			if(index==-1)
			{
				if(list.length<32)
				{
					list.push(id);
				}
				else
				{
					throw new Error("There is no available SoundChannel. Max is 32");
					return;
				}
			}else
			{
				var oldSu:SoundUnit=data[id];
				oldSu.dispose();
			}
			su.loop=loop;
			su.autoRemove=autoRemove;
			su.addEventListener(Event.COMPLETE,onSoundUnitCompleteHandler);
			data[id]=su;
			if(autoPlay)
			{
				su.play();
			}
		}
		
		/**
		 * 添加一个外部声音 
		 * @param id 声音ID 
		 * @param path 地址
		 * @param autoPlay 是否自动播放
		 * @param loop 循环播放次数，0，1均为播放1次，SoundUnit.INFINITI (-1000) 为无限循环
		 * @param autoRemove 是否自动删除，如果是将在循环播放彻底结束时候删除
		 */
		public function addExternalSound(id:String,path:String,autoPlay:Boolean=true,loop:int=0,autoRemove:Boolean=true):void
		{
			var sound:Sound=new Sound();
			sound.load(new URLRequest(path));
			addSound(id,sound,autoPlay,loop,autoRemove);
		}
		/**
		 * 添加库声音 
		 * @param id 声音ID
		 * @param className 库中类名
		 * @param autoPlay 是否自动播放
		 * @param loop 循环播放次数，0，1均为播放1次，SoundUnit.INFINITI (-1000) 为无限循环
		 * @param autoRemove 是否自动删除，如果是将在循环播放彻底结束时候删除
		 */
		public function addLibrarySound(id:String,className:String,autoPlay:Boolean=true,loop:int=0,autoRemove:Boolean=true):void
		{
			var classObj:Object=flash.utils.getDefinitionByName(className);
			var sound:Sound=Sound(new classObj());
			if(!sound)
			{
				throw new Error("Find no "+className+"!");
				return;
			}
			addSound(id,sound,autoPlay,loop,autoRemove);
		}
		/**
		 * 删除一个声音,被删除的声音将自动停止
		 * @param id 声音ID
		 * 
		 */
		public function removeSound(id:String):void
		{
			var index:int=list.indexOf(id);
			if(index==-1)
			{
				return ;
			}
			list.splice(index,1);
			var su:SoundUnit=data[id];
			if(su.hasEventListener(Event.COMPLETE))
			{
				su.removeEventListener(Event.COMPLETE,onSoundUnitCompleteHandler);
			}
			if(su)
			{
				su.dispose();
			}
			delete data[id];
			
			//su=null;
			//return su;
		}
		/**
		 * 删除所用声音 
		 * @param autoStop 是否自动停止播放
		 * 
		 */
		public function removeAllSound(autoStop:Boolean=true):void
		{
			var su:SoundUnit;
			for(var i:uint=0;i<list.length;i++)
			{
				su=data[list[i]];
				if(su.hasEventListener(Event.COMPLETE))
				{
					su.removeEventListener(Event.COMPLETE,onSoundUnitCompleteHandler);
				}
				if(su && autoStop)
				{
					su.stop();
				}
			}
			
			list=new Array();
			data=new Object();
		}
		/**
		 * 删除一个或全部暂停的声音 
		 * @param all 是否全部删除
		 * 
		 */
		public function removePauseSound(all:Boolean=false):void
		{
			var su:SoundUnit;
			for(var i:uint=0;i<list.length;i++)
			{
				su=data[list[i]];
				if(!su.isPlay)
				{
					removeSound(su.ID);
					if(all==false)
					{
						return;
					}
				}
			}					
		}
		
		/**
		 * 获得ID的SoundUnit 
		 * @param id 要获得的SoundUnit的ID
		 * @return 如果有将返回SoundUnit，否则返回 null
		 * 
		 */
		public function getSoundUint(id:String):SoundUnit
		{
			if(data[id])
			{
				return data[id];
			}
			return null;
		}
		private function onSoundUnitCompleteHandler(e:Event):void
		{
			var su:SoundUnit=SoundUnit(e.currentTarget);
			if(su.autoRemove)
			{
				removeSound(su.ID);
			}
		}
	}
}